home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / info-service / www / src / WWW / Library / Implementation / HTRules.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-23  |  8.3 KB  |  331 lines

  1. /*    Configuration manager for Hypertext Daemon        HTRules.c
  2. **    ==========================================
  3. **
  4. **
  5. ** History:
  6. **     3 Jun 91    Written TBL
  7. **    10 Aug 91    Authorisation added after Daniel Martin (pass, fail)
  8. **            Rule order in file changed
  9. **            Comments allowed with # on 1st char of rule line
  10. **      17 Jun 92       Bug fix: pass and fail failed if didn't contain '*' TBL
  11. */
  12.  
  13. /* (c) CERN WorldWideWeb project 1990,91. See Copyright.html for details */
  14. #include "HTRules.h"
  15.  
  16. #include <stdio.h>
  17. #include "tcp.h"
  18. #include "HTFile.h"
  19.  
  20. #define LINE_LENGTH 256
  21.  
  22.  
  23. typedef struct _rule {
  24.     struct _rule *    next;
  25.     HTRuleOp    op;
  26.     char *        pattern;
  27.     char *        equiv;
  28. } rule;
  29.  
  30. /*    Module-wide variables
  31. **    ---------------------
  32. */
  33.  
  34. PRIVATE rule * rules = 0;    /* Pointer to first on list */
  35. #ifndef PUT_ON_HEAD
  36. PRIVATE rule * rule_tail = 0;    /* Pointer to last on list */
  37. #endif
  38.  
  39. /*    Add rule to the list                    HTAddRule()
  40. **    --------------------
  41. **
  42. **  On entry,
  43. **    pattern        points to 0-terminated string containing a single "*"
  44. **    equiv        points to the equivalent string with * for the
  45. **            place where the text matched by * goes.
  46. **  On exit,
  47. **    returns        0 if success, -1 if error.
  48. */
  49. /*    Note that if BYTE_ADDRESSING is set, the three blocks required
  50. **    are allocated and deallocated as one. This will save time and
  51. **    storage, when malloc's allocation units are large.
  52. */
  53. #ifdef __STDC__
  54. PUBLIC int HTAddRule (HTRuleOp op, const char * pattern, const char * equiv)
  55. #else
  56. int HTAddRule(op, pattern, equiv)
  57.     HTRuleOp    op;
  58.     char *    pattern;
  59.     char *    equiv;
  60. #endif
  61. {
  62. #ifdef BYTE_ADDRESSING    /* economise on malloc() blocks */
  63.     int        length_of_pattern = strlen(pattern)+1;
  64.     rule *    temp = malloc(sizeof(*temp) +
  65.                 size_of_pattern + strlen(equiv) + 1);
  66.     char *    pPattern = (char *) &temp[1];
  67. #else
  68.     rule *    temp = (rule *)malloc(sizeof(*temp));
  69.     char *    pPattern = (char *)malloc(strlen(pattern)+1);
  70. #endif
  71.  
  72.     if (equiv) {        /* Two operands */
  73. #ifdef BYTE_ADDRESSING    /* economise on malloc() blocks */
  74.         char *    pEquiv = pPattern + length_of_pattern;
  75. #else
  76.     char *    pEquiv = (char *)malloc(strlen(equiv)+1);
  77. #endif
  78.         temp->equiv = pEquiv;
  79.         strcpy(pEquiv, equiv);
  80.     } else {
  81.         temp->equiv = 0;
  82.     }
  83.     temp->pattern = pPattern;
  84.     temp->op = op;
  85.  
  86.     strcpy(pPattern, pattern);
  87.     if (TRACE) printf("Rule: For `%s' op %i `%s'\n", pattern, op, equiv);
  88.  
  89. #ifdef PUT_ON_HEAD
  90.     temp->next = rules;
  91.     rules = temp;
  92. #else
  93.     temp->next = 0;
  94.     if (rule_tail) rule_tail->next = temp;
  95.     else rules = temp;
  96.     rule_tail = temp;
  97. #endif
  98.  
  99.         
  100.     return 0;
  101. }
  102.  
  103.  
  104. /*    Clear all rules                        HTClearRules()
  105. **    ---------------
  106. **
  107. ** On exit,
  108. **    There are no rules
  109. **    returns        0 if success, -1 if error.
  110. **
  111. ** See also
  112. **    HTAddRule()
  113. */
  114. #ifdef __STDC__
  115. int HTClearRules(void)
  116. #else
  117. int HTClearRules()
  118. #endif
  119. {
  120.     while (rules) {
  121.         rule * temp = rules;
  122.     rules = temp->next;
  123. #ifdef BYTE_ADDRESSING
  124.     free(temp);
  125. #else
  126.     free(temp->pattern);
  127.     free(temp->equiv);
  128.     free(temp);
  129. #endif
  130.     }
  131. #ifndef PUT_ON_HEAD
  132.     rule_tail = 0;
  133. #endif
  134.  
  135.     return 0;
  136. }
  137.  
  138.  
  139. /*    Translate by rules                    HTTranslate()
  140. **    ------------------
  141. **
  142. **    The most recently defined rules are applied first.
  143. **
  144. ** On entry,
  145. **    required    points to a string whose equivalent value is neeed
  146. ** On exit,
  147. **    returns        the address of the equivalent string allocated from
  148. **            the heap which the CALLER MUST FREE. If no translation
  149. **            occured, then it is a copy of te original.
  150. */
  151. #ifdef __STDC__
  152. char * HTTranslate(const char * required)
  153. #else
  154. char * HTTranslate(required)
  155.     char * required;
  156. #endif
  157. {
  158.     rule * r;
  159.     char * current = (char *)malloc(strlen(required)+1);
  160.     strcpy(current, required);
  161.     
  162.     for(r = rules; r; r = r->next) {
  163.         char * p = r->pattern;
  164.     int m;   /* Number of characters matched against wildcard */
  165.     CONST char * q = current;
  166.     for(;*p && *q; p++, q++) {   /* Find first mismatch */
  167.         if (*p!=*q) break;
  168.     }
  169.  
  170.     if (*p == '*') {        /* Match up to wildcard */
  171.         m = strlen(q) - strlen(p+1); /* Amount to match to wildcard */
  172.         if(m<0) continue;           /* tail is too short to match */
  173.         if (0!=strcmp(q+m, p+1)) continue;    /* Tail mismatch */
  174.     } else                 /* Not wildcard */
  175.         if (*p != *q) continue;    /* plain mismatch: go to next rule */
  176.  
  177.     switch (r->op) {        /* Perform operation */
  178.     case HT_Pass:                /* Authorised */
  179.             if (!r->equiv) {
  180.             if (TRACE) printf("HTRule: Pass `%s'\n", current);
  181.             return current;
  182.             }
  183.         /* Fall through ...to map and pass */
  184.         
  185.     case HT_Map:
  186.         if (*p == *q) { /* End of both strings, no wildcard */
  187.                   if (TRACE) printf(
  188.                    "For `%s' using `%s'\n", current, r->equiv);  
  189.               StrAllocCopy(current, r->equiv); /* use entire translation */
  190.         } else {
  191.           char * ins = strchr(r->equiv, '*');    /* Insertion point */
  192.               if (ins) {    /* Consistent rule!!! */
  193.             char * temp = (char *)malloc(
  194.                 strlen(r->equiv)-1 + m + 1);
  195.             strncpy(temp,     r->equiv, ins-r->equiv);
  196.             /* Note: temp may be unterminated now! */
  197.             strncpy(temp+(ins-r->equiv), q, m);  /* Matched bit */
  198.             strcpy (temp+(ins-r->equiv)+m, ins+1);    /* Last bit */
  199.                 if (TRACE) printf("For `%s' using `%s'\n",
  200.                         current, temp);
  201.             free(current);
  202.             current = temp;            /* Use this */
  203.  
  204.             } else {    /* No insertion point */
  205.             char * temp = (char *)malloc(strlen(r->equiv)+1);
  206.             strcpy(temp, r->equiv);
  207.                 if (TRACE) printf("For `%s' using `%s'\n",
  208.                         current, temp);
  209.             free(current);
  210.             current = temp;            /* Use this */
  211.             } /* If no insertion point exists */
  212.         }
  213.         if (r->op == HT_Pass) {
  214.             if (TRACE) printf("HTRule: ...and pass `%s'\n", current);
  215.             return current;
  216.         }
  217.         break;
  218.  
  219.         case HT_Invalid:
  220.         case HT_Fail:                /* Unauthorised */
  221.                 if (TRACE) printf("HTRule: *** FAIL `%s'\n", current);
  222.             return (char *)0;
  223.                         
  224.             } /* if tail matches ... switch operation */
  225.  
  226.     } /* loop over rules */
  227.  
  228.  
  229.     return current;
  230. }
  231.  
  232. /*    Load one line of configuration
  233. **    ------------------------------
  234. **
  235. **    Call this, for example, to load a X resource with config info.
  236. **
  237. ** returns    0 OK, < 0 syntax error.
  238. */
  239. PUBLIC int  HTSetConfiguration ARGS1(CONST char *, config)
  240. {
  241.     HTRuleOp op;
  242.     char * line = NULL;
  243.     char * pointer = line;
  244.     char *word1, *word2, *word3;
  245.     float quality, secs, secs_per_byte;
  246.     int status;
  247.     
  248.     StrAllocCopy(line, config);
  249.     {
  250.     char * p = strchr(line, '#');    /* Chop off comments */
  251.     if (p) *p = 0;
  252.     }
  253.     pointer = line;
  254.     word1 = HTNextField(&pointer);
  255.     if (!word1) {
  256.         free(line);
  257.     return 0;
  258.     } ;    /* Comment only or blank */
  259.     
  260.     word2 = HTNextField(&pointer);
  261.     word3 = HTNextField(&pointer);
  262.     if (!word2) {
  263.     fprintf(stderr, "HTRule: Insufficient operands: %s\n", line);
  264.     free(line);
  265.     return -2;    /*syntax error */
  266.     }
  267.  
  268.     if (0==strcasecomp(word1, "suffix")) {
  269.         char * encoding = HTNextField(&pointer);
  270.     if (pointer) status = sscanf(pointer, "%f", &quality);
  271.     else status = 0;
  272.     HTSetSuffix(word2,    word3,
  273.                 encoding ? encoding : "binary",
  274.                 status >= 1? quality : 1.0);
  275.  
  276.     } else if (0==strcasecomp(word1, "presentation")) {
  277.         if (pointer) status = sscanf(pointer, "%f%f%f",
  278.                 &quality, &secs, &secs_per_byte);
  279.         else status = 0;
  280.     HTSetPresentation(word2, word3,
  281.             status >= 1? quality         : 1.0,
  282.             status >= 2 ? secs         : 0.0,
  283.             status >= 3 ? secs_per_byte     : 0.0 );
  284.  
  285.     } else {
  286.     op =    0==strcasecomp(word1, "map")  ?    HT_Map
  287.         :    0==strcasecomp(word1, "pass") ?    HT_Pass
  288.         :    0==strcasecomp(word1, "fail") ?    HT_Fail
  289.         :                        HT_Invalid;
  290.     if (op==HT_Invalid) {
  291.         fprintf(stderr, "HTRule: Bad rule `%s'\n", config);
  292.     } else {  
  293.         HTAddRule(op, word2, word3);
  294.     } 
  295.     }
  296.     free(line);
  297.     return 0;
  298. }
  299.  
  300.  
  301. /*    Load the rules from a file                HtLoadRules()
  302. **    --------------------------
  303. **
  304. ** On entry,
  305. **    Rules can be in any state
  306. ** On exit,
  307. **    Any existing rules will have been kept.
  308. **    Any new rules will have been loaded.
  309. **    Returns        0 if no error, 0 if error!
  310. **
  311. ** Bugs:
  312. **    The strings may not contain spaces.
  313. */
  314.  
  315. int HTLoadRules ARGS1(CONST char *, filename)
  316. {
  317.     FILE * fp = fopen(filename, "r");
  318.     char line[LINE_LENGTH+1];
  319.     
  320.     if (!fp) {
  321.         if (TRACE) printf("HTRules: Can't open rules file %s\n", filename);
  322.     return -1; /* File open error */
  323.     }
  324.     for(;;) {
  325.     if (!fgets(line, LINE_LENGTH+1, fp)) break;    /* EOF or error */
  326.     (void) HTSetConfiguration(line);
  327.     }
  328.     fclose(fp);
  329.     return 0;        /* No error or syntax errors ignored */
  330. }
  331.